#include "submesh.h"
#include "resourcemanager.h"
#include "material.h"
#include "graphic.h"

namespace Engine
{
	/**********************************************************************************************************/
	SubMesh::SubMesh()
		:m_indexDataPtr(0)
		,m_faceCount(0)
	{
	}
	/**********************************************************************************************************/
	SubMesh::SubMesh(const std::string& name)
		:m_name(name)
	{
	}
	/**********************************************************************************************************/
	SubMesh::~SubMesh()
	{
		if(!m_material.IsNull())
		{
			std::string name = m_material->GetName();
			m_material.Delete();
			ResourceManager::GetSingleton().TryRemove(name);
		}
	}
	/**********************************************************************************************************/
	const std::string& SubMesh::GetName()const
	{
		return m_name;
	}
	/**********************************************************************************************************/
    const MaterialPtr SubMesh::GetMaterial() const
	{
		return m_material;
	}
	/**********************************************************************************************************/
	const HardWareBufferPtr SubMesh::GetIndexData()const
	{
		return m_indexData;
	}
	/**********************************************************************************************************/
	void SubMesh::Read(RefPtr<XmlElement> pElem)
	{
		TraverseAttributes(pElem->FirstAttribute(),mem_fun2_obj(this,&SubMesh::ReadSubMeshAttributes));
		m_indexDataPtr = reinterpret_cast<unsigned short*>(m_indexData->Lock());
		TraverseElemets(pElem->FirstChildElement(),mem_fun2_obj(this,&SubMesh::ReadSubMesh));
		m_indexData->UnLock();
	}
	/**********************************************************************************************************/
	void SubMesh::ReadSubMeshAttributes(const std::string& name, const std::string& value)
	{
		if(name == "name")
		{
			m_name = value;
		}
		else if(name == "material")
		{
			WeakUtils::UnsafeCopy(m_material, ResourceManager::GetSingleton().Create(value, "Material"));
			m_material->Load();
		}
		else if(name == "facecount")
		{
			m_faceCount = 0;
			std::stringstream buf(value);
			buf >> m_faceCount;
			m_indexData = Graphic::GetSingleton().GetRenderSystem()->CreateIndexBuffer(m_faceCount, INDEX_BUFFER_16);
			m_indexDataPtr = 0;
		}
		else
			throw std::logic_error("Unknown attribute <" + name +"> in SUBMESH");
	}
	/**********************************************************************************************************/
	void SubMesh::ReadSubMesh(RefPtr<XmlElement> pElem,const std::string& name)
	{
		if(name == "face")
		{
			if(pElem->FirstAttribute().IsNull())
				throw std::logic_error("Empty FACE node for SUBMESH");

			ValuesReader<unsigned short> reader("v1","v2","v3");

			TraverseAttributes(pElem->FirstAttribute(),mem_fun2_obj(&reader,&ValuesReader<unsigned short>::Read));

			memcpy(m_indexDataPtr++,&reader["v1"],sizeof(unsigned short));
			memcpy(m_indexDataPtr++,&reader["v2"],sizeof(unsigned short));
			memcpy(m_indexDataPtr++,&reader["v3"],sizeof(unsigned short));
		}
		else
			throw std::logic_error("Unknown child node <" + name +"> in SUBMESH");
	}
	/**********************************************************************************************************/
}
